#include <ximera/gui/cegui/guisystem.hpp>
#include <ximera/common/utils.hpp>

#include <ximera/gui/cegui/window.hpp>
#include <ximera/gui/cegui/button.hpp>
#include <ximera/gui/cegui/checkbox.hpp>
#include <ximera/gui/cegui/combobox.hpp>
#include <ximera/gui/cegui/listbox.hpp>
#include <ximera/gui/cegui/progressbar.hpp>
#include <ximera/gui/cegui/radiobutton.hpp>
#include <ximera/gui/cegui/slider.hpp>
#include <ximera/gui/cegui/spinner.hpp>
#include <ximera/gui/cegui/textbox.hpp>

#include <CEGUISystem.h>
#include <CEGUILogger.h>
#include <CEGUISchemeManager.h>
#include <CEGUIWindowManager.h>
#include <CEGUIWindow.h>

#include <boost/lexical_cast.hpp>

namespace ximera { namespace gui { namespace cegui
{
    GuiSystem::GuiSystem(system::Application& app)
        : _application(app),
          _inputHandler(app)
    {
        try
        {
            Ogre::RenderWindow* window = reinterpret_cast<Ogre::RenderWindow*>(
                boost::lexical_cast<Int64>(app.settings().value(L"ximera.ogre.renderwindow")));

            Ogre::SceneManager* scene = reinterpret_cast<Ogre::SceneManager*>(
                boost::lexical_cast<Int64>(app.settings().value(L"ximera.ogre.scenemanager")));

            _ogreRenderer.reset(new CEGUI::OgreCEGUIRenderer(window, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, scene));
            _ceguiSystem.reset(new CEGUI::System(_ogreRenderer.get()));

            CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
            _ceguiSystem->setMouseMoveScaling(30000);
        }
        catch (...)
        {
        }
    }

    GuiSystem::~GuiSystem()
    {
    }

    void GuiSystem::render()
    {
        _ceguiSystem->renderGUI();
    }

    void GuiSystem::defaultFont(String const& name)
    {
    }

    void GuiSystem::mouseCursor(String const& imageName)
    {
        _ceguiSystem->setDefaultMouseCursor("TaharezLook", string_util::wstr2str(imageName));
    }

    IWindow* GuiSystem::createWindow(String const& type, String const& name)
    {
        CEGUI::Window* window = CEGUI::WindowManager::getSingleton().createWindow(
            string_util::wstr2str(type), string_util::wstr2str(name));

        return createWindow(window);
    }

    IWindow* GuiSystem::createWindow(String const& fileName)
    {
        CEGUI::Window* window = CEGUI::WindowManager::getSingleton().loadWindowLayout(
            string_util::wstr2str(fileName));

        return createWindow(window);
    }

    void GuiSystem::activeWindow(IWindow* window)
    {
        Window* ceguiWin = static_cast<Window*>(window);
        if (!ceguiWin)
            CEGUI::System::getSingleton().setGUISheet(0);
        else
            CEGUI::System::getSingleton().setGUISheet(ceguiWin->ceguiWindow());
    }

    void GuiSystem::loadScheme(String const& fileName)
    {
        CEGUI::SchemeManager::getSingleton().loadScheme(string_util::wstr2str(fileName));
    }

    IWindow* GuiSystem::createWindow(CEGUI::Window* window)
    {
        if (CEGUI::PushButton* control = dynamic_cast<CEGUI::PushButton*>(window))
            return new Button(control);
        else if (CEGUI::Checkbox* control = dynamic_cast<CEGUI::Checkbox*>(window))
            return new Checkbox(control);
        else if (CEGUI::Combobox* control = dynamic_cast<CEGUI::Combobox*>(window))
            return new Combobox(control);
        else if (CEGUI::Listbox* control = dynamic_cast<CEGUI::Listbox*>(window))
            return new Listbox(control);
        else if (CEGUI::ProgressBar* control = dynamic_cast<CEGUI::ProgressBar*>(window))
            return new ProgressBar(control);
        else if (CEGUI::RadioButton* control = dynamic_cast<CEGUI::RadioButton*>(window))
            return new RadioButton(control);
        else if (CEGUI::Slider* control = dynamic_cast<CEGUI::Slider*>(window))
            return new Slider(control);
        else if (CEGUI::Spinner* control = dynamic_cast<CEGUI::Spinner*>(window))
            return new Spinner(control);
        else if (CEGUI::Editbox* control = dynamic_cast<CEGUI::Editbox*>(window))
            return new Textbox(control);

        return new Window(window);
    }
}}}
